package sign

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"net/http"
	"net/url"
	"sanrenx.com/xyxf/pkg/e"
	"sanrenx.com/xyxf/pkg/setting"
	"sanrenx.com/xyxf/pkg/utils"
	"sort"
	"strings"
)

// MD5 组合加密
func SetUp() gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			encryptStr string
			code       int
			data       interface{}
		)

		if c.Request.Method == "POST" && c.ContentType() == "application/json" {
			jsonBody, _ := ioutil.ReadAll(c.Request.Body)
			encryptStr = createJsonEncryptStr(string(jsonBody))
			//获取后重新写入 ioutil.ReadAll() 方法会读取后就没有了内容,
			c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(jsonBody))
		} else {
			_ = c.Request.ParseForm()
			encryptStr = createFormEncryptStr(c.Request.Form)
		}

		code = e.SUCCESS
		sign := c.GetHeader("s")
		if sign == "" {
			code = e.InvalidParams
		} else if sign != createSign(encryptStr) {
			code = e.ErrorCheckSignFail
		}

		if code != e.SUCCESS {
			c.JSON(http.StatusUnauthorized, gin.H{
				"code": code,
				"msg":  e.GetMsg(code),
				"data": data,
			})

			c.Abort()
			return
		}

		c.Next()
	}
}

// 创建签名
func createSign(encryptStr string) string {
	// 自定义 MD5 组合
	return utils.EncodeMD5(encryptStr + "&s=" + setting.AppSetting.AppSecret)
}

/**
 * @Description: POST JSON
 * @param json
 * @return string
 */
func createJsonEncryptStr(json string) string {
	keys := []string{
		"appKey=" + setting.AppSetting.AppKey,
		utils.EncodeMD5(json),
	}
	//排序
	sort.Strings(keys)
	//反转
	for i, j := 0, len(keys)-1; i < j; i, j = i+1, j-1 {
		keys[i], keys[j] = keys[j], keys[i]
	}
	return strings.Join(keys, "&")
}

/**
 * @Description: GET || POST FORM DATA
 * @param params
 * @return string
 */
func createFormEncryptStr(params url.Values) string {
	var key []string
	var str string
	for k := range params {
		if k != "s" {
			key = append(key, k)
		}
	}
	key = append(key, "appKey")
	//排序
	sort.Strings(key)
	////反转
	for i, j := 0, len(key)-1; i < j; i, j = i+1, j-1 {
		key[i], key[j] = key[j], key[i]
	}
	//拼成串
	for i := 0; i < len(key); i++ {
		var val string

		if key[i] == "appKey" {
			val = setting.AppSetting.AppKey
		} else {
			val = params.Get(key[i])
		}

		if i == 0 {
			str = fmt.Sprintf("%v=%v", key[i], val)
		} else {
			str = str + fmt.Sprintf("&%v=%v", key[i], val)
		}
	}
	return str
}
